home *** CD-ROM | disk | FTP | other *** search
/ Chip 2007 January, February, March & April / Chip-Cover-CD-2007-02.iso / Pakiet bezpieczenstwa / mini Pentoo LiveCD 2006.1 / mpentoo-2006.1.iso / livecd.squashfs / usr / lib / mozilla-firefox / include / xpcom / pldhash.h < prev    next >
C/C++ Source or Header  |  2006-05-08  |  25KB  |  581 lines

  1. /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
  2. /* ***** BEGIN LICENSE BLOCK *****
  3.  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  4.  *
  5.  * The contents of this file are subject to the Mozilla Public License Version
  6.  * 1.1 (the "License"); you may not use this file except in compliance with
  7.  * the License. You may obtain a copy of the License at
  8.  * http://www.mozilla.org/MPL/
  9.  *
  10.  * Software distributed under the License is distributed on an "AS IS" basis,
  11.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  12.  * for the specific language governing rights and limitations under the
  13.  * License.
  14.  *
  15.  * The Original Code is Mozilla JavaScript code.
  16.  *
  17.  * The Initial Developer of the Original Code is
  18.  * Netscape Communications Corporation.
  19.  * Portions created by the Initial Developer are Copyright (C) 1999-2001
  20.  * the Initial Developer. All Rights Reserved.
  21.  *
  22.  * Contributor(s):
  23.  *   Brendan Eich <brendan@mozilla.org> (Original Author)
  24.  *
  25.  * Alternatively, the contents of this file may be used under the terms of
  26.  * either of the GNU General Public License Version 2 or later (the "GPL"),
  27.  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  28.  * in which case the provisions of the GPL or the LGPL are applicable instead
  29.  * of those above. If you wish to allow use of your version of this file only
  30.  * under the terms of either the GPL or the LGPL, and not to allow others to
  31.  * use your version of this file under the terms of the MPL, indicate your
  32.  * decision by deleting the provisions above and replace them with the notice
  33.  * and other provisions required by the GPL or the LGPL. If you do not delete
  34.  * the provisions above, a recipient may use your version of this file under
  35.  * the terms of any one of the MPL, the GPL or the LGPL.
  36.  *
  37.  * ***** END LICENSE BLOCK ***** */
  38.  
  39. #ifndef pldhash_h___
  40. #define pldhash_h___
  41. /*
  42.  * Double hashing, a la Knuth 6.
  43. * GENERATED BY js/src/plify_jsdhash.sed -- DO NOT EDIT!!!
  44.  */
  45. #include "nscore.h"
  46.  
  47. PR_BEGIN_EXTERN_C
  48.  
  49. #if defined(__GNUC__) && defined(__i386__) && (__GNUC__ >= 3) && !defined(XP_OS2)
  50. #define PL_DHASH_FASTCALL __attribute__ ((regparm (3),stdcall))
  51. #else
  52. #define PL_DHASH_FASTCALL
  53. #endif
  54.  
  55. #ifdef DEBUG_XXXbrendan
  56. #define PL_DHASHMETER 1
  57. #endif
  58.  
  59. /* Table size limit, do not equal or exceed (see min&maxAlphaFrac, below). */
  60. #undef PL_DHASH_SIZE_LIMIT
  61. #define PL_DHASH_SIZE_LIMIT     PR_BIT(24)
  62.  
  63. /* Minimum table size, or gross entry count (net is at most .75 loaded). */
  64. #ifndef PL_DHASH_MIN_SIZE
  65. #define PL_DHASH_MIN_SIZE 16
  66. #elif (PL_DHASH_MIN_SIZE & (PL_DHASH_MIN_SIZE - 1)) != 0
  67. #error "PL_DHASH_MIN_SIZE must be a power of two!"
  68. #endif
  69.  
  70. /*
  71.  * Multiplicative hash uses an unsigned 32 bit integer and the golden ratio,
  72.  * expressed as a fixed-point 32-bit fraction.
  73.  */
  74. #define PL_DHASH_BITS           32
  75. #define PL_DHASH_GOLDEN_RATIO   0x9E3779B9U
  76.  
  77. /* Primitive and forward-struct typedefs. */
  78. typedef PRUint32                PLDHashNumber;
  79. typedef struct PLDHashEntryHdr  PLDHashEntryHdr;
  80. typedef struct PLDHashEntryStub PLDHashEntryStub;
  81. typedef struct PLDHashTable     PLDHashTable;
  82. typedef struct PLDHashTableOps  PLDHashTableOps;
  83.  
  84. /*
  85.  * Table entry header structure.
  86.  *
  87.  * In order to allow in-line allocation of key and value, we do not declare
  88.  * either here.  Instead, the API uses const void *key as a formal parameter,
  89.  * and asks each entry for its key when necessary via a getKey callback, used
  90.  * when growing or shrinking the table.  Other callback types are defined
  91.  * below and grouped into the PLDHashTableOps structure, for single static
  92.  * initialization per hash table sub-type.
  93.  *
  94.  * Each hash table sub-type should nest the PLDHashEntryHdr structure at the
  95.  * front of its particular entry type.  The keyHash member contains the result
  96.  * of multiplying the hash code returned from the hashKey callback (see below)
  97.  * by PL_DHASH_GOLDEN_RATIO, then constraining the result to avoid the magic 0
  98.  * and 1 values.  The stored keyHash value is table size invariant, and it is
  99.  * maintained automatically by PL_DHashTableOperate -- users should never set
  100.  * it, and its only uses should be via the entry macros below.
  101.  *
  102.  * The PL_DHASH_ENTRY_IS_LIVE macro tests whether entry is neither free nor
  103.  * removed.  An entry may be either busy or free; if busy, it may be live or
  104.  * removed.  Consumers of this API should not access members of entries that
  105.  * are not live.
  106.  *
  107.  * However, use PL_DHASH_ENTRY_IS_BUSY for faster liveness testing of entries
  108.  * returned by PL_DHashTableOperate, as PL_DHashTableOperate never returns a
  109.  * non-live, busy (i.e., removed) entry pointer to its caller.  See below for
  110.  * more details on PL_DHashTableOperate's calling rules.
  111.  */
  112. struct PLDHashEntryHdr {
  113.     PLDHashNumber       keyHash;        /* every entry must begin like this */
  114. };
  115.  
  116. #define PL_DHASH_ENTRY_IS_FREE(entry)   ((entry)->keyHash == 0)
  117. #define PL_DHASH_ENTRY_IS_BUSY(entry)   (!PL_DHASH_ENTRY_IS_FREE(entry))
  118. #define PL_DHASH_ENTRY_IS_LIVE(entry)   ((entry)->keyHash >= 2)
  119.  
  120. /*
  121.  * A PLDHashTable is currently 8 words (without the PL_DHASHMETER overhead)
  122.  * on most architectures, and may be allocated on the stack or within another
  123.  * structure or class (see below for the Init and Finish functions to use).
  124.  *
  125.  * To decide whether to use double hashing vs. chaining, we need to develop a
  126.  * trade-off relation, as follows:
  127.  *
  128.  * Let alpha be the load factor, esize the entry size in words, count the
  129.  * entry count, and pow2 the power-of-two table size in entries.
  130.  *
  131.  *   (PLDHashTable overhead)    > (PLHashTable overhead)
  132.  *   (unused table entry space) > (malloc and .next overhead per entry) +
  133.  *                                (buckets overhead)
  134.  *   (1 - alpha) * esize * pow2 > 2 * count + pow2
  135.  *
  136.  * Notice that alpha is by definition (count / pow2):
  137.  *
  138.  *   (1 - alpha) * esize * pow2 > 2 * alpha * pow2 + pow2
  139.  *   (1 - alpha) * esize        > 2 * alpha + 1
  140.  *
  141.  *   esize > (1 + 2 * alpha) / (1 - alpha)
  142.  *
  143.  * This assumes both tables must keep keyHash, key, and value for each entry,
  144.  * where key and value point to separately allocated strings or structures.
  145.  * If key and value can be combined into one pointer, then the trade-off is:
  146.  *
  147.  *   esize > (1 + 3 * alpha) / (1 - alpha)
  148.  *
  149.  * If the entry value can be a subtype of PLDHashEntryHdr, rather than a type
  150.  * that must be allocated separately and referenced by an entry.value pointer
  151.  * member, and provided key's allocation can be fused with its entry's, then
  152.  * k (the words wasted per entry with chaining) is 4.
  153.  *
  154.  * To see these curves, feed gnuplot input like so:
  155.  *
  156.  *   gnuplot> f(x,k) = (1 + k * x) / (1 - x)
  157.  *   gnuplot> plot [0:.75] f(x,2), f(x,3), f(x,4)
  158.  *
  159.  * For k of 2 and a well-loaded table (alpha > .5), esize must be more than 4
  160.  * words for chaining to be more space-efficient than double hashing.
  161.  *
  162.  * Solving for alpha helps us decide when to shrink an underloaded table:
  163.  *
  164.  *   esize                     > (1 + k * alpha) / (1 - alpha)
  165.  *   esize - alpha * esize     > 1 + k * alpha
  166.  *   esize - 1                 > (k + esize) * alpha
  167.  *   (esize - 1) / (k + esize) > alpha
  168.  *
  169.  *   alpha < (esize - 1) / (esize + k)
  170.  *
  171.  * Therefore double hashing should keep alpha >= (esize - 1) / (esize + k),
  172.  * assuming esize is not too large (in which case, chaining should probably be
  173.  * used for any alpha).  For esize=2 and k=3, we want alpha >= .2; for esize=3
  174.  * and k=2, we want alpha >= .4.  For k=4, esize could be 6, and alpha >= .5
  175.  * would still obtain.  See the PL_DHASH_MIN_ALPHA macro further below.
  176.  *
  177.  * The current implementation uses a configurable lower bound on alpha, which
  178.  * defaults to .25, when deciding to shrink the table (while still respecting
  179.  * PL_DHASH_MIN_SIZE).
  180.  *
  181.  * Note a qualitative difference between chaining and double hashing: under
  182.  * chaining, entry addresses are stable across table shrinks and grows.  With
  183.  * double hashing, you can't safely hold an entry pointer and use it after an
  184.  * ADD or REMOVE operation, unless you sample table->generation before adding
  185.  * or removing, and compare the sample after, dereferencing the entry pointer
  186.  * only if table->generation has not changed.
  187.  *
  188.  * The moral of this story: there is no one-size-fits-all hash table scheme,
  189.  * but for small table entry size, and assuming entry address stability is not
  190.  * required, double hashing wins.
  191.  */
  192. struct PLDHashTable {
  193.     const PLDHashTableOps *ops;         /* virtual operations, see below */
  194.     void                *data;          /* ops- and instance-specific data */
  195.     PRInt16             hashShift;      /* multiplicative hash shift */
  196.     uint8               maxAlphaFrac;   /* 8-bit fixed point max alpha */
  197.     uint8               minAlphaFrac;   /* 8-bit fixed point min alpha */
  198.     PRUint32            entrySize;      /* number of bytes in an entry */
  199.     PRUint32            entryCount;     /* number of entries in table */
  200.     PRUint32            removedCount;   /* removed entry sentinels in table */
  201.     PRUint32            generation;     /* entry storage generation number */
  202.     char                *entryStore;    /* entry storage */
  203. #ifdef PL_DHASHMETER
  204.     struct PLDHashStats {
  205.         PRUint32        searches;       /* total number of table searches */
  206.         PRUint32        steps;          /* hash chain links traversed */
  207.         PRUint32        hits;           /* searches that found key */
  208.         PRUint32        misses;         /* searches that didn't find key */
  209.         PRUint32        lookups;        /* number of PL_DHASH_LOOKUPs */
  210.         PRUint32        addMisses;      /* adds that miss, and do work */
  211.         PRUint32        addOverRemoved; /* adds that recycled a removed entry */
  212.         PRUint32        addHits;        /* adds that hit an existing entry */
  213.         PRUint32        addFailures;    /* out-of-memory during add growth */
  214.         PRUint32        removeHits;     /* removes that hit, and do work */
  215.         PRUint32        removeMisses;   /* useless removes that miss */
  216.         PRUint32        removeFrees;    /* removes that freed entry directly */
  217.         PRUint32        removeEnums;    /* removes done by Enumerate */
  218.         PRUint32        grows;          /* table expansions */
  219.         PRUint32        shrinks;        /* table contractions */
  220.         PRUint32        compresses;     /* table compressions */
  221.         PRUint32        enumShrinks;    /* contractions after Enumerate */
  222.     } stats;
  223. #endif
  224. };
  225.  
  226. /*
  227.  * Size in entries (gross, not net of free and removed sentinels) for table.
  228.  * We store hashShift rather than sizeLog2 to optimize the collision-free case
  229.  * in SearchTable.
  230.  */
  231. #define PL_DHASH_TABLE_SIZE(table)  PR_BIT(PL_DHASH_BITS - (table)->hashShift)
  232.  
  233. /*
  234.  * Table space at entryStore is allocated and freed using these callbacks.
  235.  * The allocator should return null on error only (not if called with nbytes
  236.  * equal to 0; but note that pldhash.c code will never call with 0 nbytes).
  237.  */
  238. typedef void *
  239. (* PR_CALLBACK PLDHashAllocTable)(PLDHashTable *table, PRUint32 nbytes);
  240.  
  241. typedef void
  242. (* PR_CALLBACK PLDHashFreeTable) (PLDHashTable *table, void *ptr);
  243.  
  244. /*
  245.  * When a table grows or shrinks, each entry is queried for its key using this
  246.  * callback.  NB: in that event, entry is not in table any longer; it's in the
  247.  * old entryStore vector, which is due to be freed once all entries have been
  248.  * moved via moveEntry callbacks.
  249.  */
  250. typedef const void *
  251. (* PR_CALLBACK PLDHashGetKey)    (PLDHashTable *table,
  252.                                       PLDHashEntryHdr *entry);
  253.  
  254. /*
  255.  * Compute the hash code for a given key to be looked up, added, or removed
  256.  * from table.  A hash code may have any PLDHashNumber value.
  257.  */
  258. typedef PLDHashNumber
  259. (* PR_CALLBACK PLDHashHashKey)   (PLDHashTable *table, const void *key);
  260.  
  261. /*
  262.  * Compare the key identifying entry in table with the provided key parameter.
  263.  * Return PR_TRUE if keys match, PR_FALSE otherwise.
  264.  */
  265. typedef PRBool
  266. (* PR_CALLBACK PLDHashMatchEntry)(PLDHashTable *table,
  267.                                       const PLDHashEntryHdr *entry,
  268.                                       const void *key);
  269.  
  270. /*
  271.  * Copy the data starting at from to the new entry storage at to.  Do not add
  272.  * reference counts for any strong references in the entry, however, as this
  273.  * is a "move" operation: the old entry storage at from will be freed without
  274.  * any reference-decrementing callback shortly.
  275.  */
  276. typedef void
  277. (* PR_CALLBACK PLDHashMoveEntry)(PLDHashTable *table,
  278.                                      const PLDHashEntryHdr *from,
  279.                                      PLDHashEntryHdr *to);
  280.  
  281. /*
  282.  * Clear the entry and drop any strong references it holds.  This callback is
  283.  * invoked during a PL_DHASH_REMOVE operation (see below for operation codes),
  284.  * but only if the given key is found in the table.
  285.  */
  286. typedef void
  287. (* PR_CALLBACK PLDHashClearEntry)(PLDHashTable *table,
  288.                                       PLDHashEntryHdr *entry);
  289.  
  290. /*
  291.  * Called when a table (whether allocated dynamically by itself, or nested in
  292.  * a larger structure, or allocated on the stack) is finished.  This callback
  293.  * allows table->ops-specific code to finalize table->data.
  294.  */
  295. typedef void
  296. (* PR_CALLBACK PLDHashFinalize)  (PLDHashTable *table);
  297.  
  298. /*
  299.  * Initialize a new entry, apart from keyHash.  This function is called when
  300.  * PL_DHashTableOperate's PL_DHASH_ADD case finds no existing entry for the
  301.  * given key, and must add a new one.  At that point, entry->keyHash is not
  302.  * set yet, to avoid claiming the last free entry in a severely overloaded
  303.  * table.
  304.  */
  305. typedef PRBool
  306. (* PR_CALLBACK PLDHashInitEntry)(PLDHashTable *table,
  307.                                      PLDHashEntryHdr *entry,
  308.                                      const void *key);
  309.  
  310. /*
  311.  * Finally, the "vtable" structure for PLDHashTable.  The first eight hooks
  312.  * must be provided by implementations; they're called unconditionally by the
  313.  * generic pldhash.c code.  Hooks after these may be null.
  314.  *
  315.  * Summary of allocation-related hook usage with C++ placement new emphasis:
  316.  *  allocTable          Allocate raw bytes with malloc, no ctors run.
  317.  *  freeTable           Free raw bytes with free, no dtors run.
  318.  *  initEntry           Call placement new using default key-based ctor.
  319.  *                      Return PR_TRUE on success, PR_FALSE on error.
  320.  *  moveEntry           Call placement new using copy ctor, run dtor on old
  321.  *                      entry storage.
  322.  *  clearEntry          Run dtor on entry.
  323.  *  finalize            Stub unless table->data was initialized and needs to
  324.  *                      be finalized.
  325.  *
  326.  * Note the reason why initEntry is optional: the default hooks (stubs) clear
  327.  * entry storage:  On successful PL_DHashTableOperate(tbl, key, PL_DHASH_ADD),
  328.  * the returned entry pointer addresses an entry struct whose keyHash member
  329.  * has been set non-zero, but all other entry members are still clear (null).
  330.  * PL_DHASH_ADD callers can test such members to see whether the entry was
  331.  * newly created by the PL_DHASH_ADD call that just succeeded.  If placement
  332.  * new or similar initialization is required, define an initEntry hook.  Of
  333.  * course, the clearEntry hook must zero or null appropriately.
  334.  *
  335.  * XXX assumes 0 is null for pointer types.
  336.  */
  337. struct PLDHashTableOps {
  338.     /* Mandatory hooks.  All implementations must provide these. */
  339.     PLDHashAllocTable   allocTable;
  340.     PLDHashFreeTable    freeTable;
  341.     PLDHashGetKey       getKey;
  342.     PLDHashHashKey      hashKey;
  343.     PLDHashMatchEntry   matchEntry;
  344.     PLDHashMoveEntry    moveEntry;
  345.     PLDHashClearEntry   clearEntry;
  346.     PLDHashFinalize     finalize;
  347.  
  348.     /* Optional hooks start here.  If null, these are not called. */
  349.     PLDHashInitEntry    initEntry;
  350. };
  351.  
  352. /*
  353.  * Default implementations for the above ops.
  354.  */
  355. NS_COM_GLUE void *
  356. PL_DHashAllocTable(PLDHashTable *table, PRUint32 nbytes);
  357.  
  358. NS_COM_GLUE void
  359. PL_DHashFreeTable(PLDHashTable *table, void *ptr);
  360.  
  361. NS_COM_GLUE PLDHashNumber
  362. PL_DHashStringKey(PLDHashTable *table, const void *key);
  363.  
  364. /* A minimal entry contains a keyHash header and a void key pointer. */
  365. struct PLDHashEntryStub {
  366.     PLDHashEntryHdr hdr;
  367.     const void      *key;
  368. };
  369.  
  370. NS_COM_GLUE const void *
  371. PL_DHashGetKeyStub(PLDHashTable *table, PLDHashEntryHdr *entry);
  372.  
  373. NS_COM_GLUE PLDHashNumber
  374. PL_DHashVoidPtrKeyStub(PLDHashTable *table, const void *key);
  375.  
  376. NS_COM_GLUE PRBool
  377. PL_DHashMatchEntryStub(PLDHashTable *table,
  378.                        const PLDHashEntryHdr *entry,
  379.                        const void *key);
  380.  
  381. NS_COM_GLUE PRBool
  382. PL_DHashMatchStringKey(PLDHashTable *table,
  383.                        const PLDHashEntryHdr *entry,
  384.                        const void *key);
  385.  
  386. NS_COM_GLUE void
  387. PL_DHashMoveEntryStub(PLDHashTable *table,
  388.                       const PLDHashEntryHdr *from,
  389.                       PLDHashEntryHdr *to);
  390.  
  391. NS_COM_GLUE void
  392. PL_DHashClearEntryStub(PLDHashTable *table, PLDHashEntryHdr *entry);
  393.  
  394. NS_COM_GLUE void
  395. PL_DHashFreeStringKey(PLDHashTable *table, PLDHashEntryHdr *entry);
  396.  
  397. NS_COM_GLUE void
  398. PL_DHashFinalizeStub(PLDHashTable *table);
  399.  
  400. /*
  401.  * If you use PLDHashEntryStub or a subclass of it as your entry struct, and
  402.  * if your entries move via memcpy and clear via memset(0), you can use these
  403.  * stub operations.
  404.  */
  405. NS_COM_GLUE const PLDHashTableOps *
  406. PL_DHashGetStubOps(void);
  407.  
  408. /*
  409.  * Dynamically allocate a new PLDHashTable using malloc, initialize it using
  410.  * PL_DHashTableInit, and return its address.  Return null on malloc failure.
  411.  * Note that the entry storage at table->entryStore will be allocated using
  412.  * the ops->allocTable callback.
  413.  */
  414. NS_COM_GLUE PLDHashTable *
  415. PL_NewDHashTable(const PLDHashTableOps *ops, void *data, PRUint32 entrySize,
  416.                  PRUint32 capacity);
  417.  
  418. /*
  419.  * Finalize table's data, free its entry storage (via table->ops->freeTable),
  420.  * and return the memory starting at table to the malloc heap.
  421.  */
  422. NS_COM_GLUE void
  423. PL_DHashTableDestroy(PLDHashTable *table);
  424.  
  425. /*
  426.  * Initialize table with ops, data, entrySize, and capacity.  Capacity is a
  427.  * guess for the smallest table size at which the table will usually be less
  428.  * than 75% loaded (the table will grow or shrink as needed; capacity serves
  429.  * only to avoid inevitable early growth from PL_DHASH_MIN_SIZE).
  430.  */
  431. NS_COM_GLUE PRBool
  432. PL_DHashTableInit(PLDHashTable *table, const PLDHashTableOps *ops, void *data,
  433.                   PRUint32 entrySize, PRUint32 capacity);
  434.  
  435. /*
  436.  * Set maximum and minimum alpha for table.  The defaults are 0.75 and .25.
  437.  * maxAlpha must be in [0.5, 0.9375] for the default PL_DHASH_MIN_SIZE; or if
  438.  * MinSize=PL_DHASH_MIN_SIZE <= 256, in [0.5, (float)(MinSize-1)/MinSize]; or
  439.  * else in [0.5, 255.0/256].  minAlpha must be in [0, maxAlpha / 2), so that
  440.  * we don't shrink on the very next remove after growing a table upon adding
  441.  * an entry that brings entryCount past maxAlpha * tableSize.
  442.  */
  443. NS_COM_GLUE void
  444. PL_DHashTableSetAlphaBounds(PLDHashTable *table,
  445.                             float maxAlpha,
  446.                             float minAlpha);
  447.  
  448. /*
  449.  * Call this macro with k, the number of pointer-sized words wasted per entry
  450.  * under chaining, to compute the minimum alpha at which double hashing still
  451.  * beats chaining.
  452.  */
  453. #define PL_DHASH_MIN_ALPHA(table, k)                                          \
  454.     ((float)((table)->entrySize / sizeof(void *) - 1)                         \
  455.      / ((table)->entrySize / sizeof(void *) + (k)))
  456.  
  457. /*
  458.  * Finalize table's data, free its entry storage using table->ops->freeTable,
  459.  * and leave its members unchanged from their last live values (which leaves
  460.  * pointers dangling).  If you want to burn cycles clearing table, it's up to
  461.  * your code to call memset.
  462.  */
  463. NS_COM_GLUE void
  464. PL_DHashTableFinish(PLDHashTable *table);
  465.  
  466. /*
  467.  * To consolidate keyHash computation and table grow/shrink code, we use a
  468.  * single entry point for lookup, add, and remove operations.  The operation
  469.  * codes are declared here, along with codes returned by PLDHashEnumerator
  470.  * functions, which control PL_DHashTableEnumerate's behavior.
  471.  */
  472. typedef enum PLDHashOperator {
  473.     PL_DHASH_LOOKUP = 0,        /* lookup entry */
  474.     PL_DHASH_ADD = 1,           /* add entry */
  475.     PL_DHASH_REMOVE = 2,        /* remove entry, or enumerator says remove */
  476.     PL_DHASH_NEXT = 0,          /* enumerator says continue */
  477.     PL_DHASH_STOP = 1           /* enumerator says stop */
  478. } PLDHashOperator;
  479.  
  480. /*
  481.  * To lookup a key in table, call:
  482.  *
  483.  *  entry = PL_DHashTableOperate(table, key, PL_DHASH_LOOKUP);
  484.  *
  485.  * If PL_DHASH_ENTRY_IS_BUSY(entry) is true, key was found and it identifies
  486.  * entry.  If PL_DHASH_ENTRY_IS_FREE(entry) is true, key was not found.
  487.  *
  488.  * To add an entry identified by key to table, call:
  489.  *
  490.  *  entry = PL_DHashTableOperate(table, key, PL_DHASH_ADD);
  491.  *
  492.  * If entry is null upon return, then either the table is severely overloaded,
  493.  * and memory can't be allocated for entry storage via table->ops->allocTable;
  494.  * Or if table->ops->initEntry is non-null, the table->ops->initEntry op may
  495.  * have returned false.
  496.  *
  497.  * Otherwise, entry->keyHash has been set so that PL_DHASH_ENTRY_IS_BUSY(entry)
  498.  * is true, and it is up to the caller to initialize the key and value parts
  499.  * of the entry sub-type, if they have not been set already (i.e. if entry was
  500.  * not already in the table, and if the optional initEntry hook was not used).
  501.  *
  502.  * To remove an entry identified by key from table, call:
  503.  *
  504.  *  (void) PL_DHashTableOperate(table, key, PL_DHASH_REMOVE);
  505.  *
  506.  * If key's entry is found, it is cleared (via table->ops->clearEntry) and
  507.  * the entry is marked so that PL_DHASH_ENTRY_IS_FREE(entry).  This operation
  508.  * returns null unconditionally; you should ignore its return value.
  509.  */
  510. NS_COM_GLUE PLDHashEntryHdr * PL_DHASH_FASTCALL
  511. PL_DHashTableOperate(PLDHashTable *table, const void *key, PLDHashOperator op);
  512.  
  513. /*
  514.  * Remove an entry already accessed via LOOKUP or ADD.
  515.  *
  516.  * NB: this is a "raw" or low-level routine, intended to be used only where
  517.  * the inefficiency of a full PL_DHashTableOperate (which rehashes in order
  518.  * to find the entry given its key) is not tolerable.  This function does not
  519.  * shrink the table if it is underloaded.  It does not update stats #ifdef
  520.  * PL_DHASHMETER, either.
  521.  */
  522. NS_COM_GLUE void
  523. PL_DHashTableRawRemove(PLDHashTable *table, PLDHashEntryHdr *entry);
  524.  
  525. /*
  526.  * Enumerate entries in table using etor:
  527.  *
  528.  *   count = PL_DHashTableEnumerate(table, etor, arg);
  529.  *
  530.  * PL_DHashTableEnumerate calls etor like so:
  531.  *
  532.  *   op = etor(table, entry, number, arg);
  533.  *
  534.  * where number is a zero-based ordinal assigned to live entries according to
  535.  * their order in table->entryStore.
  536.  *
  537.  * The return value, op, is treated as a set of flags.  If op is PL_DHASH_NEXT,
  538.  * then continue enumerating.  If op contains PL_DHASH_REMOVE, then clear (via
  539.  * table->ops->clearEntry) and free entry.  Then we check whether op contains
  540.  * PL_DHASH_STOP; if so, stop enumerating and return the number of live entries
  541.  * that were enumerated so far.  Return the total number of live entries when
  542.  * enumeration completes normally.
  543.  *
  544.  * If etor calls PL_DHashTableOperate on table with op != PL_DHASH_LOOKUP, it
  545.  * must return PL_DHASH_STOP; otherwise undefined behavior results.
  546.  *
  547.  * If any enumerator returns PL_DHASH_REMOVE, table->entryStore may be shrunk
  548.  * or compressed after enumeration, but before PL_DHashTableEnumerate returns.
  549.  * Such an enumerator therefore can't safely set aside entry pointers, but an
  550.  * enumerator that never returns PL_DHASH_REMOVE can set pointers to entries
  551.  * aside, e.g., to avoid copying live entries into an array of the entry type.
  552.  * Copying entry pointers is cheaper, and safe so long as the caller of such a
  553.  * "stable" Enumerate doesn't use the set-aside pointers after any call either
  554.  * to PL_DHashTableOperate, or to an "unstable" form of Enumerate, which might
  555.  * grow or shrink entryStore.
  556.  *
  557.  * If your enumerator wants to remove certain entries, but set aside pointers
  558.  * to other entries that it retains, it can use PL_DHashTableRawRemove on the
  559.  * entries to be removed, returning PL_DHASH_NEXT to skip them.  Likewise, if
  560.  * you want to remove entries, but for some reason you do not want entryStore
  561.  * to be shrunk or compressed, you can call PL_DHashTableRawRemove safely on
  562.  * the entry being enumerated, rather than returning PL_DHASH_REMOVE.
  563.  */
  564. typedef PLDHashOperator
  565. (* PR_CALLBACK PLDHashEnumerator)(PLDHashTable *table, PLDHashEntryHdr *hdr,
  566.                                       PRUint32 number, void *arg);
  567.  
  568. NS_COM_GLUE PRUint32
  569. PL_DHashTableEnumerate(PLDHashTable *table, PLDHashEnumerator etor, void *arg);
  570.  
  571. #ifdef PL_DHASHMETER
  572. #include <stdio.h>
  573.  
  574. NS_COM_GLUE void
  575. PL_DHashTableDumpMeter(PLDHashTable *table, PLDHashEnumerator dump, FILE *fp);
  576. #endif
  577.  
  578. PR_END_EXTERN_C
  579.  
  580. #endif /* pldhash_h___ */
  581.